﻿using Newtonsoft.Json;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Anay.TaskScheduling.Common;
using Anay.TaskScheduling.JobConfig;

namespace Anay.TaskScheduling.Job
{
    /// <summary>
    /// 基础job.
    /// 主要功能：通过Post或Get方式请求指定接口.
    /// </summary>
    public class BaseJob : IJob
    {

        public static bool isLock = false;
        public static object lock_obj = new object();
        public static bool isLockTaskResult = false;
        public static object lock_objTaskResult = new object();
        public string ConfigId = "";
        private Common.IConfigHelper ConfigHelper = new ConfigFactory().GetInstance();


        public async Task Execute(IJobExecutionContext context)
        {
            await Task.Run(() =>

            {
                while (isLock)
                {
                    System.Threading.Thread.Sleep(5000);
                }
                //用于线程安全
                lock (lock_obj)
                {
                    isLock = true;
                }
                Ep_task_config task_Config = new Ep_task_config();
                try
                {

                    try
                    {
                        JobDataMap jobDataMap = context.JobDetail.JobDataMap;
                        ConfigId = jobDataMap.GetString("ConfigId");
                        task_Config = ConfigHelper.GetTask_config(ConfigId);
                    }
                    catch (Exception ex)
                    {
                        Anay.Logging.LogHelper.Write("执行job时（获取数据库job配置）：" + ex.Message + "\r\n" + ex.StackTrace);
                    }
                    if (task_Config != null && task_Config.IsEnabled.Trim() == "0")
                    {
                        try
                        {
                            //运行业务逻辑
                            Executeing(task_Config, context).GetAwaiter().GetResult();
                        }
                        catch (Exception ex)
                        {

                            Anay.Logging.LogHelper.Write("执行job时（运行业务逻辑）：" + ex.Message + "\r\n" + ex.StackTrace);
                        }

                    }
                }
                catch (Exception ex)
                {

                    Anay.Logging.LogHelper.Write("执行job时（整体业务逻辑）：" + ex.Message + "\r\n" + ex.StackTrace);
                }
                finally
                {
                    isLock = false;
                    task_Config.UpdateDate = DateTime.Now;
                    ConfigHelper.UpdateLastRunTime(task_Config);
                   
                }
            });
        }

        public virtual async Task Executeing(Ep_task_config task_Config, IJobExecutionContext context)
        {
            Dictionary<string, Action<Ep_task_config>> dic = new Dictionary<string, Action<Ep_task_config>>()
            {
                { "Get", (e) => { GetHandler(e); } },
                { "POST", (e) => { PostHandler(e); } },
            };
            await Task.Run(() =>
            {
                WriteLogaAsync(task_Config, task_Config.JobName + "JOB开始：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n");

                HttpHelper httpHelper = new HttpHelper();
                if (task_Config.LastRunTime == null)
                {
                    task_Config.LastRunTime = ConfigHelper.GetLastRunTime(task_Config.Id);
                }

                if (dic.ContainsKey(task_Config.Metthod)) 
                {
                    dic[task_Config.Metthod](task_Config);
                }

                WriteLogaAsync(task_Config, task_Config.JobName + "JOB结束：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n");
            });


        }

        /// <summary>
        /// Get请求处理开始.
        /// </summary>
        /// <param name="config"></param>
        private void GetHandler(Ep_task_config config)
        {
            try
            {
                string url = config.JobUrl;
                if (url.IndexOf("?") == -1)
                    url += "?1=1";
                url += "&last_edit_time="
                    + ConfigHelper.GetLastRunTime(config.Id).Value.ToString("yyyy-MM-dd HH:mm:ss")
                    + "&templateid=" + config.TemplateId ?? ""
                    + "&taskid=" + config.Id
                    + "&jobname=" + config.JobName;
                HttpGo(() =>
                {
                    return HttpHelper.GetAsync(url, System.Text.Encoding.UTF8);
                }, config);
            }
            catch (Exception ex)
            {
                Anay.Logging.LogHelper.Write("执行job时（GET）：" + ex.Message + "\r\n" + ex.StackTrace);
            }
        }

        /// <summary>
        /// Post请求处理开始.
        /// </summary>
        /// <param name="config"></param>
        private void PostHandler(Ep_task_config config)
        {
            try
            {
                Dictionary<string, string> dictionary = null;
                if (!string.IsNullOrWhiteSpace(config.JsonString))
                {
                    try
                    {
                        dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(config.JsonString);
                    }
                    catch (Exception ex)
                    {
                        Anay.Logging.LogHelper.Write("执行job时（序列化POST参数:" + config.JsonString + "）：" + ex.Message + "\r\n" + ex.StackTrace);

                        dictionary = new Dictionary<string, string>();
                    }

                }
                else
                {
                    dictionary = new Dictionary<string, string>();
                }
                dictionary.Add("last_edit_time", ConfigHelper.GetLastRunTime(config.Id).Value.ToString("yyyy-MM-dd HH:mm:ss"));
                dictionary.Add("templateid", config.TemplateId ?? "");
                dictionary.Add("taskid", config.Id);
                dictionary.Add("jobname", config.JobName);
                HttpGo(() =>
                {
                    return HttpHelper.PostAsync(config.JobUrl, dictionary, System.Text.Encoding.UTF8);
                }, config);

            }
            catch (Exception ex)
            {
                Anay.Logging.LogHelper.Write("执行job时（POST）：" + ex.Message + "\r\n" + ex.StackTrace);
            }
        }

        private Task HttpGo(Func<Task<HttpResult>> func, Ep_task_config _Task_Config)
        {
            return Task.Run(async () =>
           {
               var result = await func();
               string path = AppDomain.CurrentDomain.BaseDirectory + @"/Log/TaskResult/" + _Task_Config.JobName + "/"; 
               if (!Directory.Exists(path))
               {
                   Directory.CreateDirectory(path);
               }
               path += _Task_Config.JobName + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
               FileInfo file = new FileInfo(path);
               if (!file.Exists)
               {

                   FileStream fs;
                   fs = File.Create(path);
                   fs.Close();
               }

               using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
               {
                   using (StreamWriter sw = new StreamWriter(fs))
                   {
                       sw.WriteLine(DateTime.Now.ToString() + "\r\n" + result.html + "\r\n\r\n");
                       sw.Close();
                   }

                   fs.Close();
                   
               }
           });
        }

        private async Task WriteLogaAsync(Ep_task_config task_Config, string msg)
        {
            await Task.Run(() =>
            {
                while (isLockTaskResult)
                {
                    System.Threading.Thread.Sleep(5000);
                }
                //由于写日志的时候是异步写，任务调度时间又快 可能会堵住，还是锁住会比较好
                lock (lock_objTaskResult)
                {
                    isLockTaskResult = true;
                }
                try
                {
                    WriteLog(task_Config, msg);
                }
                catch (Exception ex)
                {
                    Anay.Logging.LogHelper.Write(ex.Message);
                }
                finally
                {
                    isLockTaskResult = false;
                }


            });
        }
        private void WriteLog(Ep_task_config task_Config, string msg)
        {

            string path = AppDomain.CurrentDomain.BaseDirectory + @"/Log/TaskRun/" + task_Config.JobName + "/";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            path += task_Config.JobName + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
            FileInfo file = new FileInfo(path);
            if (!file.Exists)
            {

                FileStream fs;
                fs = File.Create(path);
                fs.Close();
            }

            using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.WriteLine(msg);
                }
                fs.Close();
            }
        }
    }
}
